/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package cpasl;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javax.swing.JOptionPane;

/**
 *
 * @author seanm_000
 */
public class CpaslManager {

    private static final SimpleDateFormat FILE_NAME_FORMAT = new SimpleDateFormat("MM_dd_yyyy_hh_mm_ss");

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("EEE MMM dd yy hh:mm:ss.SSS");
    
    private int FILE_COUNT = 11;
	
    private static final String VIDEO_DIRECTORY_KEY = "video.directory";
    private static final String IMAGES_DIRECTORY_KEY = "images.directory";
    private static final String CPASL_OUTPUT_DIRECTORY_KEY = "cpasl.output.directory"; 
    private static final String PART_1_INSTRUCTIONS_KEY = "part1.instructions";
    private static final String PART_2_INSTRUCTIONS_KEY = "part2.instructions";
    private static final String PART_3_INSTRUCTIONS_KEY = "part3.instructions";
    private static final String PART_1_ROUNDS_KEY = "part1.rounds";
    private static final String PART_2_ROUNDS_KEY = "part2.rounds";
    private static final String PRIME_1_LONG_VIDEO_KEY = "prime1.video.long";
    private static final String PRIME_1_SHORT_VIDEO_KEY = "prime1.video.short";
    private static final String PRIME_2_VIDEO_KEY = "prime2.video";
    
    private static CpaslManager instance = null;
           
    private Stage stage = null;
    
    private InitialGroup initialGroup = null;
    
    private PictureChoiceGroup choiceGroup = null;
    
    private VideoGroup videoGroup = null;
    
    private PartTwoVideoGroup partTwoVideoGroup = null;
    
    private Group blankGroup = new Group();
    
    private boolean prime1 = true;
    
    private String participantId = null;
    
    private Timer timer = new Timer();
    
    private DecimalFormat numberFormat = new DecimalFormat("000");
    
    private Vector<Image> images = new Vector<Image>();
    
    private File videoDirectory = null;
    private File imagesDirectory = null;
    private File outputDirectory = null;
    private File prime1VideoLongFile = null;
    private File prime1VideoShortFile = null;
    private File prime2VideoFile = null;
    
    private int part1Rounds = 0;
    private int part2Rounds = 0;
    
    private boolean part1 = true;
    
    private LinkedList<InstructionsPair> part1InstructionPairs = 
            new LinkedList<InstructionsPair>();
    private LinkedList<InstructionsPair> part2InstructionPairs = 
            new LinkedList<InstructionsPair>();
    private LinkedList<InstructionsPair> part3InstructionPairs = 
            new LinkedList<InstructionsPair>();
    
    private int part1InstructionsIndex = 0;
    private int part2InstructionsIndex = 0;
    
    private BufferedWriter part1OutputFileWriter = null;
    
    private BufferedWriter part2OutputFileWriter = null;
    
    private int pictureClickCount = 0;
    
    private int randomVideoIndex = 0;
    
    private long lastDisplayTime = 0;
    
    private Random random = new Random(Calendar.getInstance().getTimeInMillis());
    
    private int videoChoiceIndex = -1;
    
    private int videoSelectionCount = 0;
    
    private RandomExampleDoneGroup randomExampleDoneGroup = new RandomExampleDoneGroup();
    
    private VideoChoiceExampleDoneGroup choiceExampleDoneGroup = 
            new VideoChoiceExampleDoneGroup();
    
    private LinkedList<Integer> part1VideoIndicesVector = 
            new LinkedList<Integer>();
    
    private LinkedList<PartTwoVideoIndices> part2VideoIndicesVector = 
            new LinkedList<PartTwoVideoIndices>();
    
    private PartTwoVideoIndices videoIndices = null;
    
    private LinkedList<Integer> part1PrimeIndices = new LinkedList<Integer>();
    private LinkedList<Integer> part2PrimeIndices = new LinkedList<Integer>();
    
    private Groups nextExampleGroup = null;
    
    private String age = "";
    
    private String gender = "";
    
    private String otherGender = "";
    
    private String ethnicBackground = "";
    
    private String race = "";
    
    private String otherRace = "";
    
    private String dominantHand = "";
    
    private String hearingStatus = "";
    
    private boolean identifyWithBigD = false;
    
    private String nativeLanguage = "";
    
    private String preferredLanguage = "";
    
    private String exposureToAsl = "";
    
    private String startAgeAsl = "";
    
    private String frequencyOfAslUse = "";   
    
    private String dateString = "";
    
    public static CpaslManager getInstance() {
        if (instance == null) {
            instance = new CpaslManager();
        }
        return instance;
    }
    
    private CpaslManager() {
        
        try {
            FileInputStream propertiesStream = new FileInputStream(System.getProperty("user.home") + "/SignLanguage.properties");
            Properties cpaslProperties = new Properties();
            cpaslProperties.load(propertiesStream);

            checkProperty(cpaslProperties, VIDEO_DIRECTORY_KEY);
            checkProperty(cpaslProperties, IMAGES_DIRECTORY_KEY);
            checkProperty(cpaslProperties, CPASL_OUTPUT_DIRECTORY_KEY);
            checkProperty(cpaslProperties, PART_1_INSTRUCTIONS_KEY);
            checkProperty(cpaslProperties, PART_2_INSTRUCTIONS_KEY);
            checkProperty(cpaslProperties, PART_3_INSTRUCTIONS_KEY);
            checkProperty(cpaslProperties, PART_1_ROUNDS_KEY);
            checkProperty(cpaslProperties, PART_2_ROUNDS_KEY);

            videoDirectory = getDirectory(cpaslProperties, VIDEO_DIRECTORY_KEY);
            imagesDirectory = getDirectory(cpaslProperties, IMAGES_DIRECTORY_KEY);
            outputDirectory = getDirectory(cpaslProperties, CPASL_OUTPUT_DIRECTORY_KEY);
            prime1VideoLongFile = getFile(cpaslProperties, PRIME_1_LONG_VIDEO_KEY);
            prime1VideoShortFile = getFile(cpaslProperties, PRIME_1_SHORT_VIDEO_KEY);
            prime2VideoFile = getFile(cpaslProperties, PRIME_2_VIDEO_KEY);
            
            try {
                part1Rounds = Integer.valueOf(cpaslProperties.getProperty(PART_1_ROUNDS_KEY));
                part2Rounds = Integer.valueOf(cpaslProperties.getProperty(PART_2_ROUNDS_KEY));
                String part1InstructionsString = 
                        cpaslProperties.getProperty(PART_1_INSTRUCTIONS_KEY);
                String[] part1InstructionsKeys = part1InstructionsString.split(",");
                for (String part1InstructionsKey : part1InstructionsKeys) {
                    File textFile = getFile(cpaslProperties, 
                            part1InstructionsKey.trim() + ".text");
                    File videoFile = getFile(cpaslProperties,
                            part1InstructionsKey.trim() + ".video");
                    InstructionsPair instructionsPair = 
                            new InstructionsPair(textFile, videoFile);
                    part1InstructionPairs.add(instructionsPair);
                }
                String part2InstructionsString =
                        cpaslProperties.getProperty(PART_2_INSTRUCTIONS_KEY);
                String[] part2InstructionsKeys = part2InstructionsString.split(",");
                for (String part2InstructionsKey : part2InstructionsKeys) {
                    File textFile = getFile(cpaslProperties, 
                            part2InstructionsKey.trim() + ".text");
                    File videoFile = getFile(cpaslProperties,
                            part2InstructionsKey.trim() + ".video");
                    InstructionsPair instructionsPair = 
                            new InstructionsPair(textFile, videoFile);
                    part2InstructionPairs.add(instructionsPair);
                }
                String part3InstructionsString =
                        cpaslProperties.getProperty(PART_3_INSTRUCTIONS_KEY);
                String[] part3InstructionsKeys = part3InstructionsString.split(",");
                for (String part3InstructionsKey : part3InstructionsKeys) {
                    File textFile = getFile(cpaslProperties, 
                            part3InstructionsKey.trim() + ".text");
                    File videoFile = getFile(cpaslProperties,
                            part3InstructionsKey.trim() + ".video");
                    InstructionsPair instructionsPair = 
                            new InstructionsPair(textFile, videoFile);
                    part3InstructionPairs.add(instructionsPair);
                }
                
                dateString = FILE_NAME_FORMAT.format(new Date());
		String part1OutputFilePath = outputDirectory.getAbsolutePath() + "/Cpasl_Part1_" + dateString + ".txt";
		String part2OutputFilePath = outputDirectory.getAbsolutePath() + "/Cpasl_Part2_" + dateString + ".txt";
		try {
                    part1OutputFileWriter = new BufferedWriter(new FileWriter(part1OutputFilePath));
                    part1OutputFileWriter.write("Subject,Trial,Display,Response,Reaction Time (ms)");
                    part1OutputFileWriter.newLine();
                    part1OutputFileWriter.flush();
                    
                    part2OutputFileWriter = new BufferedWriter(new FileWriter(part2OutputFilePath));
                    part2OutputFileWriter.write("Subject,Trial,VideoA,VideoB,DisplayVideo,Response,Reaction Time (ms)");
                    part2OutputFileWriter.newLine();
                    part2OutputFileWriter.flush();
		} catch (IOException e) {
                    e.printStackTrace();
		}
            }
            catch (NumberFormatException nfe) {
                System.exit(0);
            }
        }
        catch (IOException ioe) {
            JOptionPane.showMessageDialog(null, ioe.getMessage(), "EXITING", JOptionPane.ERROR_MESSAGE);
        }
        fillPart1VideoIndicesVector();
        fillPart2VideoIndicesVector();
        for (int i = part1Rounds; i > 0; i -= 12) {
            part1PrimeIndices.add(i);
        }
        for (int i = part2Rounds; i > 0; i -= 12) {
            part2PrimeIndices.add(i);
        }
    }

    private static void checkProperty(Properties cpaslProperties, String key) {
        if (!cpaslProperties.containsKey(key)) {
            JOptionPane.showMessageDialog(null, "Missing property " + key, "Missing Property", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
    }

    private static File getFile(Properties cpaslProperties, String key) {
        String filePath = cpaslProperties.getProperty(key);
        File file = new File(filePath);
        if (!file.exists()) {
            JOptionPane.showMessageDialog(null, "File doesn't exist " + filePath, "Bad Directory", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        return file;
    }

    private static File getDirectory(Properties cpaslProperties, String key) {
        String directoryPath = cpaslProperties.getProperty(key);
        File directoryFile = new File(directoryPath);
        if (!directoryFile.exists()) {
            JOptionPane.showMessageDialog(null, "Directory doesn't exist " + directoryPath, "Bad Directory", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        else if (!directoryFile.isDirectory()) {
            JOptionPane.showMessageDialog(null, "Given path isn't a directory:  " + directoryPath, "Bad Directory", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        return directoryFile;
    }
    
    private void fillPart1VideoIndicesVector() {
        for (int i = 0; i < FILE_COUNT; i++) {
            part1VideoIndicesVector.add(i);
        }
        Collections.shuffle(part1VideoIndicesVector);
    }
    
    private void fillPart2VideoIndicesVector() {
        for (int i = 0; i < (FILE_COUNT-1); i++) {
            int indexA = i;
            int indexB = i+1;
            part2VideoIndicesVector.add(
                    new PartTwoVideoIndices(indexA, indexB, indexA));
            part2VideoIndicesVector.add(
                    new PartTwoVideoIndices(indexB, indexA, indexA));
            part2VideoIndicesVector.add(
                    new PartTwoVideoIndices(indexA, indexB, indexB));
            part2VideoIndicesVector.add(
                    new PartTwoVideoIndices(indexB, indexA, indexB));
        }
        Collections.shuffle(part2VideoIndicesVector);
    }

    public boolean isPrime1() {
        return prime1;
    }

    public void setPrime1(boolean prime1) {
        this.prime1 = prime1;
    }

    public String getParticipantId() {
        return participantId;
    }

    public void setParticipantId(String participantId) {
        this.participantId = participantId;
    }

    public int getFileCount() {
        return FILE_COUNT;
    }

    public Vector<Image> getImages() {
        return images;
    }
    
    public void start(Stage primaryStage) {
        stage = primaryStage;
        stage.setOnCloseRequest(new EventHandler<WindowEvent>() {

            @Override
            public void handle(WindowEvent event) {
                System.exit(0);
            }
        });
        
        initialGroup = new InitialGroup(stage);
        videoGroup = new VideoGroup();
        partTwoVideoGroup = new PartTwoVideoGroup();
        
        stage.setFullScreen(true);
        stage.setFullScreenExitHint("");
        Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
        stage.setWidth(primaryScreenBounds.getWidth());
        stage.setHeight(primaryScreenBounds.getHeight());
        Scene scene = new Scene(initialGroup, 540, 210);
        File stylesheetsFile = new File(System.getProperty("user.home") + "/stylesheet.css");
        if (stylesheetsFile.exists()) {
            scene.getStylesheets().add(stylesheetsFile.toURI().toString());
        }
        stage.setScene(scene);
        stage.show();
    }
    
    public void switchToDisplay(Groups newDisplay, long blankTime) {
        stage.getScene().setRoot(blankGroup);
        timer.schedule(new DisplayTask(newDisplay), blankTime);
    }
    
    public void switchToDisplay(Groups newDisplay, Group intermediateDisplay, long blankTime) {
        stage.getScene().setRoot(intermediateDisplay);
        timer.schedule(new DisplayTask(newDisplay), blankTime);
    }

    public File getImagesDirectory() {
        return imagesDirectory;
    }

    public File getVideoDirectory() {
        return videoDirectory;
    }

    public void setVideoDirectory(File videoDirectory) {
        this.videoDirectory = videoDirectory;
    }
    
    public void writePictureChoice(int pictureIndex) {
        if (part1 && nextExampleGroup == null) {
            Date clickDate = new Date();
            long clickTime = clickDate.getTime();
            pictureClickCount++;
            String update = participantId + "," + pictureClickCount + "," + randomVideoIndex + "," + pictureIndex + "," + (clickTime - lastDisplayTime);
            try {
                part1OutputFileWriter.write(update);
                part1OutputFileWriter.newLine();
                part1OutputFileWriter.flush();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }
    
    public void writeVideoChoice() {
        if (!part1 && nextExampleGroup == null) {
            Date clickDate = new Date();
            long clickTime = clickDate.getTime();
            videoSelectionCount++;
            String update = participantId + "," + videoSelectionCount + "," 
                    + videoIndices.getVideoIndexA() + "," 
                    + videoIndices.getVideoIndexB() + "," 
                    + videoIndices.getVideoIndexAOrB() + "," 
                    + videoChoiceIndex + ","+ (clickTime - lastDisplayTime);
            try {
                part2OutputFileWriter.write(update);
                part2OutputFileWriter.newLine();
                part2OutputFileWriter.flush();
            } catch (IOException ioe) {
                    ioe.printStackTrace();
            }
        }
    }
    
    private class DisplayTask extends TimerTask {
        
        private Groups nextDisplay = null;
        
        public DisplayTask(Groups nextDisplay) {
            this.nextDisplay = nextDisplay;
        }

        @Override
        public void run() {
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    switch (nextDisplay) {
                        case RANDOM_VIDEO: {
                            if (part1) {
                                switchToRandomVideo();
                            }
                            break;
                        }
                        case CHOICE: {
                            videoGroup.setLabel("");
                            if (choiceGroup == null) {
                                choiceGroup = new PictureChoiceGroup();
                            }
                            if (nextExampleGroup != null) {
                                choiceGroup.setNextGroup(nextExampleGroup);
                            }
                            else {
                                if (part1PrimeIndices.contains(part1Rounds)) {
                                    choiceGroup.setNextGroup(Groups.PRIME);
                                }
                                else {
                                    choiceGroup.setNextGroup(Groups.RANDOM_VIDEO);
                                }
                            }
                            stage.getScene().setRoot(choiceGroup);
                            stage.setFullScreen(true);
                            Date clickDate = new Date();
                            lastDisplayTime = clickDate.getTime();
                            break;
                        }
                        case INSTRUCTIONS_NEXT: {
                            switchToInstructions();
                            break;
                        }
                        case VIDEO_A: {
                            switchToVideoA();
                            break;
                        }
                        case VIDEO_B: {
                            stage.getScene().setRoot(partTwoVideoGroup);
                            partTwoVideoGroup.loadVideo(videoIndices.getVideoIndexB(), false);
                            partTwoVideoGroup.displayB();
                            partTwoVideoGroup.getMediaPlayer().play();
                            break;
                        }
                        case VIDEO_A_OR_B_DISPLAY:
                            stage.getScene().setRoot(partTwoVideoGroup);
                            partTwoVideoGroup.loadVideo(videoIndices.getVideoIndexAOrB(), true);
                            partTwoVideoGroup.displayAorB();
                            partTwoVideoGroup.getMediaPlayer().play();
                            break;
                        case VIDEO_A_OR_B_CHOICE:
                            if (nextExampleGroup != null) {
                                partTwoVideoGroup.setGroups(nextExampleGroup);
                            }
                            else if (part2Rounds <= 0) {
                                partTwoVideoGroup.setGroups(Groups.INSTRUCTIONS_NEXT);
                            }
                            else if (part2PrimeIndices.contains(part2Rounds)) {
                                partTwoVideoGroup.setGroups(Groups.PRIME);
                            }
                            else {
                                partTwoVideoGroup.setGroups(Groups.VIDEO_A);
                            }
                            partTwoVideoGroup.displayChoice();
                            stage.getScene().setRoot(partTwoVideoGroup);
                            stage.setFullScreen(true);
                            Date clickDate = new Date();
                            lastDisplayTime = clickDate.getTime();
                            break;
                        case PART_1_EXAMPLE_PRIME:
                            stage.getScene().setRoot(videoGroup);
                            if (prime1) {
                                videoGroup.loadVideo(prime1VideoLongFile);
                            }
                            else {
                                videoGroup.loadVideo(prime2VideoFile);
                            }
                            videoGroup.setLabel("Instructor");
                            videoGroup.centerVideo();
                            videoGroup.getMediaPlayer().setOnEndOfMedia(new Runnable() {

                                @Override
                                public void run() {
                                    CpaslManager.getInstance().switchToDisplay(Groups.PART_1_EXAMPLE_1, 250);
                                }

                            });
                            videoGroup.getMediaPlayer().play();
                            break;
                        case PART_2_EXAMPLE_PRIME:
                            stage.getScene().setRoot(videoGroup);
                            if (prime1) {
                                videoGroup.loadVideo(prime1VideoLongFile);
                            }
                            else {
                                videoGroup.loadVideo(prime2VideoFile);
                            }
                            videoGroup.setLabel("Instructor");
                            videoGroup.centerVideo();
                            videoGroup.getMediaPlayer().setOnEndOfMedia(new Runnable() {

                                @Override
                                public void run() {
                                    CpaslManager.getInstance().switchToDisplay(Groups.PART_2_EXAMPLE_1, 250);
                                }
                                
                            });
                            videoGroup.getMediaPlayer().play();
                            break;
                        case PART_1_EXAMPLE_1:
                            nextExampleGroup = Groups.PART_1_EXAMPLE_2;
                            videoGroup.setLabel("Student");
                            stage.getScene().setRoot(videoGroup);
                            videoGroup.loadVideo(3, false);
                            videoGroup.randomizeVideoLocation();
                            videoGroup.getMediaPlayer().play();
                            break;
                        case PART_1_EXAMPLE_2:
                            nextExampleGroup = Groups.PART_1_EXAMPLE_DONE;
                            videoGroup.setLabel("Student");
                            stage.getScene().setRoot(videoGroup);
                            videoGroup.loadVideo(5, false);
                            videoGroup.randomizeVideoLocation();
                            videoGroup.getMediaPlayer().play();
                            break;
                        case PART_2_EXAMPLE_1:
                            nextExampleGroup = Groups.PART_2_EXAMPLE_2;
                            videoIndices = new PartTwoVideoIndices(5, 6, 6);
                            stage.getScene().setRoot(partTwoVideoGroup);
                            partTwoVideoGroup.loadVideo(videoIndices.getVideoIndexA(), false);
                            partTwoVideoGroup.displayA();
                            partTwoVideoGroup.getMediaPlayer().play();
                            break;
                        case PART_2_EXAMPLE_2:
                            nextExampleGroup = Groups.PART_2_EXAMPLE_DONE;
                            videoIndices = new PartTwoVideoIndices(7, 8, 7);
                            stage.getScene().setRoot(partTwoVideoGroup);
                            partTwoVideoGroup.loadVideo(videoIndices.getVideoIndexA(), false);
                            partTwoVideoGroup.displayA();
                            partTwoVideoGroup.getMediaPlayer().play();
                            break;
                        case PART_1_EXAMPLE_DONE:
                            nextExampleGroup = null;
                            stage.getScene().setRoot(randomExampleDoneGroup);
                            break;
                        case PART_2_EXAMPLE_DONE:
                            nextExampleGroup = null;
                            stage.getScene().setRoot(choiceExampleDoneGroup);
                            break;
                        case PRIME: 
                            switchToPrimeVideo();
                            break;
                        case AGE:
                            stage.getScene().setRoot(new AgeGridPane());
                            break;
                        case GENDER:
                            stage.getScene().setRoot(new GenderGridPane());
                            break;
                        case ETHNIC:
                            stage.getScene().setRoot(new EthnicGridPane());
                            break;
                        case RACE:
                            stage.getScene().setRoot(new RaceGridPane());
                            break;
                        case HAND:
                            stage.getScene().setRoot(new HandGridPane());
                            break;
                        case HEARING:
                            stage.getScene().setRoot(new HearingGridPane());
                            break;
                        case BIG_D:
                            stage.getScene().setRoot(new BigDGridPane());
                            break;
                        case NATIVE:
                            stage.getScene().setRoot(new NativeGridPane());
                            break;
                        case PREFERRED:
                            stage.getScene().setRoot(new PreferredGridPane());
                            break;
                        case EXPOSURE:
                            stage.getScene().setRoot(new ExposureGridPane());
                            break;
                        case ASL_START:
                            stage.getScene().setRoot(new AslStartGridPane());
                            break;
                        case ASL_FREQUENCY:
                            stage.getScene().setRoot(new AslFrequencyGridPane());
                            break;
                        case THANK_YOU:
                            stage.getScene().setRoot(new ThankYouGridPane());
                            
                            
                    }
                }
                
                private void switchToRandomVideo() {
                    if (part1Rounds > 0) {
                        if (part1VideoIndicesVector.isEmpty()) {
                            fillPart1VideoIndicesVector();
                        }
                        randomVideoIndex = part1VideoIndicesVector.pop();
                        if (nextExampleGroup == null) { //Not an example.
                            part1Rounds--;
                        }
                        stage.getScene().setRoot(videoGroup);
                        videoGroup.loadVideo(randomVideoIndex, false);
                        
                        videoGroup.randomizeVideoLocation();
                        videoGroup.getMediaPlayer().play();
                    }
                    else {
                        part1 = false;
                        switchToInstructions();
                    }
                }
                
                private void switchToInstructions() {
                    LinkedList<InstructionsPair> instructionPairs = null;
                    if (part1) {
                        instructionPairs = part1InstructionPairs;
                    }
                    else if (part2Rounds > 0) {
                        instructionPairs = part2InstructionPairs;
                    }
                    else {
                        instructionPairs = part3InstructionPairs;
                    }
                    if (!instructionPairs.isEmpty()) {
                        InstructionsPair instructionsPair = instructionPairs.pop();
                        Groups nextGroup = Groups.INSTRUCTIONS_NEXT;
                        if (instructionPairs.isEmpty()) {
                            if (part1) {
                                nextGroup = Groups.PART_1_EXAMPLE_PRIME;
                            }
                            else if (part2Rounds > 0) {
                                nextGroup = Groups.PART_2_EXAMPLE_PRIME;
                            }
                            else {
                                nextGroup = Groups.AGE;
                            }
                        }
                        InstructionsGroup instructionsGroup = 
                                new InstructionsGroup(
                                        instructionsPair.getTextFile(), 
                                        instructionsPair.getVideoFile(), nextGroup);
                        stage.getScene().setRoot(instructionsGroup);
                        stage.setFullScreen(true);
                        instructionsGroup.play();
                    }
                    else {
                        switchToPrimeVideo();
                    }
                }
                
                private void switchToPrimeVideo() {
                    stage.getScene().setRoot(videoGroup);
                    if (prime1) {
                        videoGroup.loadVideo(prime1VideoShortFile);
                    }
                    else {
                        videoGroup.loadVideo(prime2VideoFile);
                    }
                    videoGroup.centerVideo();
                    videoGroup.getMediaPlayer().setOnEndOfMedia(new Runnable() {

                        @Override
                        public void run() {
                            if (part1) {
                                CpaslManager.getInstance().switchToDisplay(Groups.RANDOM_VIDEO, 250);
                            }
                            else {
                                CpaslManager.getInstance().switchToDisplay(Groups.VIDEO_A, 250);
                            }
                        }

                    });
                    videoGroup.getMediaPlayer().play();
                }
                
                private void switchToVideoA() {
                    if (part2Rounds > 0) {
                        if (part2VideoIndicesVector.isEmpty()) {
                            fillPart2VideoIndicesVector();
                        }
                        if (nextExampleGroup == null) { //Not an example.
                            part2Rounds--;
                        }
                        videoIndices = part2VideoIndicesVector.pop();
                        stage.getScene().setRoot(partTwoVideoGroup);
                        partTwoVideoGroup.loadVideo(videoIndices.getVideoIndexA(), false);
                        partTwoVideoGroup.displayA();
                        partTwoVideoGroup.getMediaPlayer().play();
                    }
                    else {
                        shutdown();
                    }
                    
                }
            });
        }
        
    }
    
    private class InstructionsPair {
        
        private File textFile;
        private File videoFile;
        
        public InstructionsPair(File textFile, File videoFile) {
            this.textFile = textFile;
            this.videoFile = videoFile;
        }

        public File getTextFile() {
            return textFile;
        }

        public File getVideoFile() {
            return videoFile;
        }
    }
    
    public void shutdown() {
        try {
            part1OutputFileWriter.close();
            part2OutputFileWriter.close();
        } catch (IOException ex) {
            Logger.getLogger(CpaslManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.exit(0);
    }
    
    public void setVideoASelected() {
        this.videoChoiceIndex = videoIndices.getVideoIndexA();
    }
    
    public void setVideoBSelected() {
        this.videoChoiceIndex = videoIndices.getVideoIndexB();
    }
    
    public File getVideoFile(int videoIndex, boolean x) {
        String fileName = videoIndex + "0";
        if (videoIndex < 10) {
            fileName = "0" + fileName;
        }
        if (x) {
            fileName = "X" + fileName; 
        }
        File mp4File = new File(CpaslManager.getInstance().getVideoDirectory().getAbsolutePath() + "/" + fileName + ".mp4");
        return mp4File;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void setOtherGender(String otherGender) {
        this.otherGender = otherGender;
    }

    public void setEthnicBackground(String ethnicBackground) {
        this.ethnicBackground = ethnicBackground;
    }

    public void setRace(String race) {
        this.race = race;
    }

    public void setOtherRace(String otherRace) {
        this.otherRace = otherRace;
    }

    public void setDominantHand(String dominantHand) {
        this.dominantHand = dominantHand;
    }

    public void setHearingStatus(String hearingStatus) {
        this.hearingStatus = hearingStatus;
    }

    public void setIdentifyWithBigD(boolean identifyWithBigD) {
        this.identifyWithBigD = identifyWithBigD;
    }

    public void setNativeLanguage(String nativeLanguage) {
        this.nativeLanguage = nativeLanguage;
    }

    public void setPreferredLanguage(String preferredLanguage) {
        this.preferredLanguage = preferredLanguage;
    }

    public void setExposureToAsl(String exposureToAsl) {
        this.exposureToAsl = exposureToAsl;
    }

    public void setStartAgeAsl(String startAgeAsl) {
        this.startAgeAsl = startAgeAsl;
    }

    public void setFrequencyOfAslUse(String frequencyOfAslUse) {
        this.frequencyOfAslUse = frequencyOfAslUse;
    }
    
    public void writeQuestionnaire() {
        String questionnaireFilePath = outputDirectory.getAbsolutePath() + "/Questionnaire_" + dateString + ".txt";
        try {
            BufferedWriter questionnaireFileWriter = new BufferedWriter(new FileWriter(questionnaireFilePath));
            questionnaireFileWriter.write("Age,Gender,Other Gender,Ethnic Background,Race,Other Race,Dominant Hand,Hearing Status,Identify,Native Language,Preferred Language,ASL Exposure,ASL Start Age,ASL Use");
            questionnaireFileWriter.newLine();
            StringBuilder output = new StringBuilder();
            output.append(age);
            output.append(",");
            output.append(gender);
            output.append(",");
            output.append(otherGender);
            output.append(",");
            output.append(ethnicBackground);
            output.append(",");
            output.append(race);
            output.append(",");
            output.append(otherRace);
            output.append(",");
            output.append(dominantHand);
            output.append(",");
            output.append(hearingStatus);
            output.append(",");
            output.append(identifyWithBigD);
            output.append(",");
            output.append(nativeLanguage);
            output.append(",");
            output.append(preferredLanguage);
            output.append(",");
            output.append(exposureToAsl);
            output.append(",");
            output.append(startAgeAsl);
            output.append(",");
            output.append(frequencyOfAslUse);
            questionnaireFileWriter.write(output.toString());
            questionnaireFileWriter.newLine();
            questionnaireFileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private class PartTwoVideoIndices {
    
        private int videoIndexA = -1;

        private int videoIndexB = -1;

        private int videoIndexAOrB = -1;
        
        public PartTwoVideoIndices(int videoIndexA, int videoIndexB, 
                int videoIndexAOrB) {
            this.videoIndexA = videoIndexA;
            this.videoIndexB = videoIndexB;
            this.videoIndexAOrB = videoIndexAOrB;
        }

        public int getVideoIndexA() {
            return videoIndexA;
        }

        public int getVideoIndexB() {
            return videoIndexB;
        }

        public int getVideoIndexAOrB() {
            return videoIndexAOrB;
        }
    }
}
